/****************************************Copyright (c)**********************************************
**                               		特飞科技公司
**
* 文    件 : 具有SPI接口和GPIO的TLA2518小型8通道12位ADC 驱动头文件
* 作    者 : 李海洋
* 版    本 ：v1.0
* 完成时间 : 2023年6月22日
* 描    述 ：该驱动只支持软件片选且在外部使能片选信号. 使用步骤:
*			1#使用该驱动时应在Includes.h中包含该头文件, 且位于配置定义或Config.h头文件之后!
*			  需要在配置头文件或配置定义定义以下配置宏定义
*			  #define USE_SPI_NUM		1	//定义使用SPI数量
*			  #define NO_USE_FREE_RTOS	//如果不使用操作系统需要明确给出定义
*			2#在c文档中定义SPI驱动对象的结构指针
*			  sSPI_DRIVER *pXXX;
*			3#调用SPI_Init给pXXX赋值
*			  SPI_Init(&pXXX, &spi_handle, CpltSemHandle);
*			4#使能片选信号然后根据需要分别调用以下3个方法. 这些方法属于同步调用
*			  SPI_Only_Tx, SPI_Only_Rx, SPI_Tx_Rx
**--------------------------------------------------------------------------------------------------
* 修 改 人 ：
* 版    本 ：
* 修改时间 : 年月日
* 修改内容 : 
****************************************************************************************************
*/
#pragma once

#include "SPI_Driver.h"

#pragma region //===TLA2518寄存器定义===
//系统状态寄存器定义
typedef union 
{
	uint8_t reg; //寄存器字节内容
	struct 
	{
		uint8_t BOR			: 1; //上电开机复位标志, 写1清除
		uint8_t r1			: 1; //保留位
		uint8_t CRCERR_FUSE	: 1; //器件上电配置是否出错, 出错=1后必须复位器件或重新上电
		uint8_t OSR_DONE	: 1; //过采样滤波完成状态, =1完成写1清除
		uint8_t r45			: 2; //保留位
		uint8_t SEQ_STATUS	: 1; //通道序列器状态, =1序列正在进行
		uint8_t r7			: 1; //保留位
	};
} SystemStatus_t;
//一般配置寄存器定义
typedef	union 
{
	uint8_t reg; //寄存器字节内容
	struct 
	{
		uint8_t RST			: 1; //=1软复位, 复位完毕=0 =>BOR=1
		uint8_t CAL			: 1; //=1校准ADC零偏, 校完=0
		uint8_t CH_RST		: 1; //=1b所有通道设置为模拟输入，不管其他寄存器中的配置。
		uint8_t r37			: 5;
	};
} GeneralCfg_t;
typedef	union
{
	uint8_t reg;
	struct 
	{
		uint8_t CPOL_CPHA	: 2; //设置SPI通信的极性和相位, 复位=00
		uint8_t r23			: 2;
		uint8_t APPEND_STATUS : 2; //向输出数据附加4位通道ID或状态标志。00=不追加, 01=追加4bit的通道ID, 10,11保留
		uint8_t r6			: 1;
		uint8_t FIX_PAT		: 1; //1=当读ADC设备输出固定的数据位，这有助于调试与设备的通信。
	};
} DataCfg_t; //数据配置寄存器定义
typedef enum
{
	NoAveraging		= 0,
	Sample2			= 1,
	Sample4			= 2,
	Sample8			= 3,
	Sample16		= 4,
	Sample32		= 5,
	Sample64		= 6,
	Sample128		= 7
} OSR_Select_t; //选择过采样次数
enum SampleCycle
{
	Tsc1us	= 0,
	Tsc1us5	= 1,
	Tsc2us	= 2,
	Tsc3us	= 3,
	Tsc4us	= 4,
	Tsc6us	= 5,
	Tsc8us,
	Tsc12us,
	Tsc16us,
	Tsc24us,
	Tsc32us,
	Tsc48us,
	Tsc64us,
	Tsc96us,
	Tsc128us,
	Tsc192us,
};
typedef union
{
	uint8_t reg;
	struct 
	{
		uint8_t CLK_DIV		: 4; //
		uint8_t OSC_SEL		: 1; //选择用于内部时序生成的振荡器。0=高速, 1=低功耗
	};
} OPMODE_CFG_t; //操作模式配置寄存器
typedef enum
{
	CHANNEL0_AS_GPIO = 0x01,
	CHANNEL1_AS_GPIO = 0x02,
	CHANNEL2_AS_GPIO = 0x04,
	CHANNEL3_AS_GPIO = 0x08,
	CHANNEL4_AS_GPIO = 0x10,
	CHANNEL5_AS_GPIO = 0x20,
	CHANNEL6_AS_GPIO = 0x40,
	CHANNEL7_AS_GPIO = 0x80,
} PIN_CFG_t; //引脚配置成GPIO时的枚举值
typedef enum
{
	GPIO0_AS_OUTPUT = 0x01,
	GPIO1_AS_OUTPUT = 0x02,
	GPIO2_AS_OUTPUT = 0x04,
	GPIO3_AS_OUTPUT = 0x08,
	GPIO4_AS_OUTPUT = 0x10,
	GPIO5_AS_OUTPUT = 0x20,
	GPIO6_AS_OUTPUT = 0x40,
	GPIO7_AS_OUTPUT = 0x80,
} GPIO_CFG_t; //引脚配置成数字输出时的枚举值
//输出引脚配置成推挽时的枚举值
typedef enum
{
	GPO0_AS_PUSH_PULL = 0x01,
	GPO1_AS_PUSH_PULL = 0x02,
	GPO2_AS_PUSH_PULL = 0x04,
	GPO3_AS_PUSH_PULL = 0x08,
	GPO4_AS_PUSH_PULL = 0x10,
	GPO5_AS_PUSH_PULL = 0x20,
	GPO6_AS_PUSH_PULL = 0x40,
	GPO7_AS_PUSH_PULL = 0x80,
} GPO_DRIVE_CFG_t;
//扫描模拟输入通道的序列配置寄存器定义
typedef union 
{
	uint8_t reg;
	struct 
	{
		uint8_t SEQ_MODE	: 2; //选择模拟输入通道的扫描模式。00=手动;01=自动序列;10=动态即时序列模式。11=保留。
		uint8_t r23			: 2;
		uint8_t SEQ_START	: 1; //当使用自动序列模式时，控制通道序列的启动。
	};
} SEQUENCE_CFG_t;
//手动模式通道选择寄存器定义
typedef struct
{
	uint8_t MANUAL_CHID	: 4; //在手动模式下，该字段包含下一次ADC转换的模拟输入通道的4位通道ID。1xxx=保留。
} CHANNEL_SEL_t;

#pragma pack(1)
typedef struct
{
	SystemStatus_t system_status;	//系统状态寄存器
	GeneralCfg_t general_cfg;		//一般配置寄存器
	DataCfg_t data_cfg;				//数据配置寄存器
	OSR_Select_t osr_cfg;			//过采样配置寄存器
	OPMODE_CFG_t op_mode_cfg;		//操作模式配置寄存器
	PIN_CFG_t pin_cfg;				//引脚配置寄存器, 配置设备通道AIN/GPIO[7:0]作为模拟输入=0或GPIO=1。
	uint8_t reg6;					//保留
	GPIO_CFG_t gpio_cfg;			//配置GPIO[7:0]为数字输入=0或数字输出=1。
	uint8_t reg8;					//保留
	GPO_DRIVE_CFG_t gpo_drive_cfg;	//配置数字输出GPO[7:0]为开漏=0或推挽=1输出。
	uint8_t regA;					//保留
	uint8_t gpo_value;				//在数字输出GPO上设置逻辑电平[7:0]。
	uint8_t regC;					//保留
	uint8_t gpi_value;				//回读通道上配置的数字输入的逻辑电平。
	uint8_t regE;					//保留
	uint8_t regF;					//保留
	SEQUENCE_CFG_t sequence_cfg;	//扫描模拟输入通道的序列配置寄存器
	CHANNEL_SEL_t channel_sel;		//手动模式时通道选择寄存器
	uint8_t auto_seq_ch_sel;		//选择哪些模拟输入通道AIN[7:0]为自动序列扫描。0=扫描序列中未启用模拟输入通道。1=在扫描序列中开启模拟输入通道。
} TLA2518_Reg_t;
#pragma pack()

#define TLA2518_Reg		((TLA2518_Reg_t*)0)

enum CmdOpcode
{
	cmd_NO_OP		= 0x00,	//空操作
	cmd_READ_REG	= 0x10,	//单个寄存器读取
	cmd_WRITE_REG	= 0x08,	//单个寄存器写入
	cmd_SET_BIT		= 0x18,	//设置位
	cmd_CLR_BIT		= 0x20,	//位清除
};
#pragma endregion

#pragma region //===方法===
/*
********************************************************************************
 *描述: 初始化TLA2518
 ******************************************************************************/
void TLA2518_Init(void *handle/*[I]指向外设句柄*/,
	osSemaphoreId DoneSemId/*[I]SPI通讯完成信号量句柄*/,
	osMutexId MutexId/*[I]互斥句柄*/);

/*
********************************************************************************
*描述: 获得给定通道ID的adc转换结果
*返回: 16bit转换结果
*******************************************************************************/
uint16_t TLA2518_GetADC(uint8_t channel);	/*通道ID:0=>AIN0...7=>AIN7*/
#pragma endregion

